﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using RSSFeedReader.Data.Models;
using RSSFeedReader.Resources;
using RSSFeedReader.ViewModels.Messages;

namespace RSSFeedReader.ViewModels
{
    /// <summary>
    /// Class to add a new feed to the <see cref="RSSFeedReader.Data.Models.ChannelDataSource"/>.
    /// </summary>
    public class AddNewFeedViewModel : MyViewModelBase, IDataErrorInfo
    {
        #region Fields

        string _feedUrl;
        string _clipboardText;
        readonly Channel _folder;

        #endregion

        #region Constructor

        /// <summary>
        /// Initialize a new instance of the <see cref="RSSFeedReader.ViewModels.AddNewFeedViewModel"/> class.
        /// </summary>
        public AddNewFeedViewModel()
        {
        }

        /// <summary>
        /// Initialize a new instance of the <see cref="RSSFeedReader.ViewModels.AddNewFeedViewModel"/> class.
        /// </summary>
        /// <param name="channel">The <see cref="Channel"/> folder to add the feed to.</param>
        public AddNewFeedViewModel(Channel channel)
            : this()
        {
            if (channel == null)
                throw new ArgumentNullException("channel");

            _folder = channel;
        }

        #endregion

        #region Commands

        #region AddNewFeedCommand
        private RelayCommand _addNewFeedCommand;

        /// <summary>
        /// Gets the <see cref="AddNewFeedCommand"/>.
        /// </summary>
        public RelayCommand AddNewFeedCommand
        {
            get
            {
                return _addNewFeedCommand ?? (_addNewFeedCommand = new RelayCommand(
                    () =>
                    {
                        if (IsNewFeed())
                        {
                            if (_folder != null)
                            {
                                ChannelDataSource.Instance.AddChannel(FeedUrl, _folder);
                            }
                            else
                            {
                                ChannelDataSource.Instance.AddChannel(FeedUrl);
                            }
                            CloseView();
                        }
                        else
                        {
                            ShowDialogMessage("The feed all ready exists", Strings.ApplicationName,
                                              MessageBoxButton.OK, MessageBoxImage.Information);
                        }
                    }
                    ,
                    () => !string.IsNullOrEmpty(_feedUrl) && ChannelDataSource.Instance.IsValidUrl(_feedUrl)));
            }
        }
        #endregion

        #region AutoPasteUrlCommand
        private RelayCommand _autoPasteUrlCommand;

        /// <summary>
        /// Gets the <see cref="AutoPasteUrlCommand"/>.
        /// </summary>
        public RelayCommand AutoPasteUrlCommand
        {
            get
            {
                return _autoPasteUrlCommand ?? (_autoPasteUrlCommand = new RelayCommand(
                    () =>
                    {
                        FeedUrl = _clipboardText;
                    }
                    ,
                    () =>
                    {
                        _clipboardText = Clipboard.GetText().Trim();
                        return !string.IsNullOrEmpty(_clipboardText) && ChannelDataSource.Instance.IsValidUrl(_clipboardText)
                            && string.IsNullOrEmpty(FeedUrl);
                    }));
            }
        }
        #endregion

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the url to add.
        /// </summary>
        public string FeedUrl
        {
            get { return _feedUrl; }
            set
            {
                if (_feedUrl == value)
                    return;

                _feedUrl = value;
                RaisePropertyChanged("FeedUrl");
            }
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Gets the validation error for the specified property.
        /// </summary>
        /// <param name="propertyName">The property being validated.</param>
        /// <returns>The error message if validation fails, or null if validation is passed.</returns>
        string GetValidationError(string propertyName)
        {
            if (propertyName != "FeedUrl")
                return null;

            string error = null;

            switch (propertyName)
            {
                case "FeedUrl":
                    error = ValidateUrl();
                    break;

                default:
                    Debug.Fail("Unexpected property being validated on feed: " + propertyName);
                    break;
            }

            if (error != null)
            {
                Logger.LogMessage(Strings.LogTypeWarning, string.Format("Validation on url feed error = {0}", error));
            }
            return error;
        }

        /// <summary>
        /// Validates the url being added.
        /// </summary>
        /// <returns>The error message, or null if url was validated successfully.</returns>
        string ValidateUrl()
        {
            if (string.IsNullOrEmpty(FeedUrl))
                return Strings.Channel_Url_IsMissing;

            if (!ChannelDataSource.Instance.IsValidUrl(FeedUrl))
                return Strings.Channel_Url_Invalid;

            return null;
        }

        /// <summary>
        /// Gets a value indicating if the feed being added all ready exists
        /// in the <see cref="RSSFeedReader.Data.Models.ChannelDataSource"/> instance.
        /// </summary>
        /// <returns></returns>
        bool IsNewFeed()
        {
            return !ChannelDataSource.Instance.ContainsChannel(_feedUrl);
        }

        #endregion

        #region IDataErrorInfo Members

        /// <summary>
        /// Gets an error message indicating what is wrong with this object.
        /// </summary>
        string IDataErrorInfo.Error
        {
            get { return null; }
        }

        /// <summary>
        /// Gets the error message for the property with the given name.
        /// </summary>
        /// <param name="propertyName">The name of the property whose error message to get.</param>
        /// <returns>The error message for the property.</returns>
        string IDataErrorInfo.this[string propertyName]
        {
            get { return GetValidationError(propertyName); }
        }

        #endregion
    }
}
